package net.wesc.ac.server;

/**
 * Robinson-Stokes简单水化模型，于1948年提出。详细请参考
 * [1] R. H. Stokes and R. A. Robinson. Ionic hydration and activity in electrolyte solutions. J. Am. Chem. Soc., 1948.
 * 模型方程参见用户手册方程(4.3.1)
 * 在此使用方程(4.3.1)所示的2参数模型，如需使用简化形式可参考[1]。
 * 方程(4.3.1)中a,h为调节参数。a的物理意义与Debye-Huckel理论中不相同，这里表示水和离子的离子半径，h表示离子的水合数。
 * v为每摩尔电解质解离后所产生的离子的总的物质的量，I为离子强度，Za为阴离子所带电荷数，Zc为阳离子所带电荷数，m为电解质的质量摩尔浓度。
 * aw为溶剂水的活度。A=0.509，B=0.3291，与Debye-Huckel方程完全相同。
 */
public class LMRS implements LMfunc
{  
  static final int a0 = 0; //a
  static final int a1 = 1; //h
  static final double A0 = 0.509;
  static final double B0 = 3.291;
  static final double temp0 = 298.15;
  static int Zc;
  static int Za;
  static int Va;
  static int Vc;
  static int V;
  static double temp = temp0;
  static double A = A0;
  static double B = B0;
  
  public LMRS(int tZc, int tZa, double ttemp){
	  Zc = tZc;
	  Za = tZa;
	  Vc = Za;
	  Va = Zc;
	  V = Va+Vc;
	  temp = ttemp;
	  A = A0*Math.pow(temp0/temp, 1.5);
	  B = B0*Math.pow(temp0/temp, 0.5);
  }
  
  public double[] initial()
  {
    double[] a = new double[2];
    a[a0] = 0.3;
    a[a1] = 4;
    return a;
  } //initial

  public double val(double[] x, double[] a){
	  double I = 0.5*(Va*x[0]*Math.pow(Za, 2)+Vc*x[0]*Math.pow(Zc, 2)); //I ionic strength
      return (-A*Math.abs(Za*Zc)*Math.sqrt(I))/(1+B*a[a0]*Math.sqrt(I))-a[a1]/V*Math.log10(x[1])-Math.log10(1+0.018*x[0]*(V-a[a1]));
  } //val
  
  public double grad(double[] x, double[] a, int a_k){
	  if (a_k == a0){
		  double I = 0.5*(Va*x[0]*Math.pow(Za, 2)+Vc*x[0]*Math.pow(Zc, 2)); //I ionic strength
		  return (A*I*B*Math.abs(Za*Zc))/(Math.pow(1+B*a[a0]*Math.sqrt(I),2));
	  }
	  if (a_k == a1){
		  return -Math.log10(x[1])/V+0.018*x[0]/(Math.log10(1+0.018*x[0]*(V-a[a1])));
	  }
	  else {
		  assert false;
		  return 0.;
	  }
  } //grad
} //DHTest
